package com.sun.xacml.cond;

/*
 * @(#)TimeInRangeFunction.java
 *
 * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistribution of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 * 
 *   2. Redistribution in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 * 
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed or intended for use in
 * the design, construction, operation or maintenance of any nuclear facility.
 */

import com.sun.xacml.EvaluationCtx;

import com.sun.xacml.attr.AttributeSelector;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.BagAttribute;
import com.sun.xacml.attr.BooleanAttribute;
import com.sun.xacml.attr.DateAttribute;
import com.sun.xacml.attr.DayOfWeekAttribute;
import com.sun.xacml.attr.StringAttribute;
import com.sun.xacml.attr.TimeAttribute;

import com.sun.xacml.cond.EvaluationResult;
import com.sun.xacml.cond.FunctionBase;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


/**
 * This class implements the proposed time-in-range function, which takes
 * three time values and returns true if the first value falls between the
 * second and the third value. This is not currently a standard XACML
 * function, though it has been proposed to the TC and is being considered
 * for XACML 2.0 (inclusion is quite likely). If approved, this function is
 * likely to be "standard" than the 2.0 release, since this has been proposed
 * as an errata item (this functionality was supposed to be handled in 1.0).
 * This function is not currently in the standard XACML namespace, but will
 * be moved there as soon as it has been approved.
 * <p>
 * Note that this function allows any time ranges less than 24 hours. In
 * other words, it is not bound by normal day boundries (midnight GMT), but
 * by the minimum time in the range. This means that ranges like 9am-5pm
 * are supported, as are ranges like 5pm-9am.
 *
 * @since 1.1
 * @author seth proctor
 */
public class DayOfWeekInRange extends FunctionBase
{

    /**
     * The identifier for this function
     */
    public static final String NAME =
        "http://research.sun.com/projects/xacml/names/function#dayofweek-in-range";

    /**
     * The number of milliseconds in a minute
     */
    public static final long MILLIS_PER_MINUTE = 1000 * 60;

    /**
     * The number of milliseconds in a day
     */
    public static final long MILLIS_PER_DAY = MILLIS_PER_MINUTE * 60 * 24;

	private Object[] argsValues;

    /**
     * Default constructor.
     */
    public DayOfWeekInRange() {
        super(NAME, 0, TimeAttribute.identifier, false, 3,
              BooleanAttribute.identifier, false);
    }

    /**
     * Evaluates the time-in-range function, which takes three
     * <code>TimeAttribute</code> values. This function return true
     * if the first value falls between the second and third values
     * (ie., on or after the second time and on or before the third
     * time). If no time zone is specified for the second and/or third
     * time value, then the timezone from the first time value is
     * used. This lets you say time-in-range(current-time, 9am, 5pm)
     * and always have the evaluation happen in your current-time
     * timezone.
     *
     * @param inputs a <code>List</code> of <code>Evaluatable</code>
     *               objects representing the arguments passed to the function
     * @param context the respresentation of the request
     *
     * @return an <code>EvaluationResult</code> containing true or false
     */
    public EvaluationResult evaluate(List inputs, EvaluationCtx context) {
    	
    	ArrayList<AttributeValue> argValues = new ArrayList();
        System.out.println("sizzzzz = " + inputs.size());
        EvaluationResult result = evalArgs(inputs, context, argValues);

        // check if any errors occured while resolving the inputs
        if (result != null)
            return result;
    
        
       
        DateAttribute attr = (DateAttribute)(argValues.get(0));
        //  day of week of current day 
        int middleDay = attr.getDayOfWeek();
        System.out.println("xxxxxxxxxxxxxxxxxx= " + middleDay);
        int minDay = -1;
        System.out.println(((StringAttribute)argValues.get(1)));
        
        // get the integer of day of week of the second arg
        if (((StringAttribute)argValues.get(1)).getValue().equals("Sunday"))
        {
            minDay = 0;
            System.out.print("maxday = " + minDay + " "+ minDay);
        }
        else if (((StringAttribute)argValues.get(1)).getValue().equals( "Monday"))
        	minDay = 1;
        else if (((StringAttribute)argValues.get(1)).getValue().equals( "Tuesday"))
            minDay = 2;
        else if (((StringAttribute)argValues.get(1)).getValue().equals( "Wednesday"))
            minDay = 3;
        else if (((StringAttribute)argValues.get(1)).getValue().equals( "Thursday"))
            minDay = 4;
        else if (((StringAttribute)argValues.get(1)).getValue().equals( "Friday"))
            minDay = 5;
        else if (((StringAttribute)argValues.get(1)).getValue().equals( "Saturday"))
            minDay = 6;
        
        int maxDay = -1;
        //get the integer of day of week of the third arg
        if (((StringAttribute)argValues.get(2)).getValue().equals( "Sunday"))
            maxDay = 0;
        else if (((StringAttribute)argValues.get(2)).getValue().equals( "Monday"))
        	maxDay = 1;
        else if (((StringAttribute)argValues.get(2)).getValue().equals( "Tuesday"))
            maxDay = 2;
        else if (((StringAttribute)argValues.get(2)).getValue().equals( "Wednesday"))
            maxDay = 3;
        else if (((StringAttribute)argValues.get(2)).getValue().equals( "Thursday"))
            maxDay = 4;
        else if (((StringAttribute)argValues.get(2)).getValue().equals( "Friday"))
            maxDay = 5;
        else if (((StringAttribute)argValues.get(2)).getValue().equals( "Saturday"))
            maxDay = 6;
            
        // first off, if the min and max are the same, then this can only
        // be true is the middle is also the same value
        if (minDay == maxDay)
            return EvaluationResult.getInstance(middleDay == minDay);


       
        // we're in the range if the middle is now between middleDay and maxDay
        return EvaluationResult.
            getInstance((middleDay <= maxDay) && middleDay >= minDay);
    }
    
    public EvaluationResult evalArgs(List params, EvaluationCtx context, ArrayList<AttributeValue> argValues) {
    		Iterator it = params.iterator();
    		System.out.println("sssssssss = " + params.size());
    		while (it.hasNext()) {
    			System.out.println("it = "  + 1);
    			// get and evaluate the next parameter
    			Evaluatable eval = (Evaluatable)(it.next());
    			EvaluationResult result = eval.evaluate(context);

    			// If there was an error, pass it back...
    			if (result.indeterminate())
    				return result;

				// ...otherwise save it and keep going
				//Dua vao dac ta luan van truoc
				//Gia tri dau vao thu 1 la AttributeValue
				//Gia tri dau vao thu 2 la AttributeSelector hoac AttributeDesignator
    			if(result.getAttributeValue() instanceof StringAttribute)
    			{
    				argValues.add((StringAttribute) result.getAttributeValue());
    				
    				//System.out.println("result + " + ((GeometryAttribute) result.getAttributeValue()).getGeometry());
    				System.out.println("aaaaaaaaaaaaaaaaaxxx = "  + argValues.get(1));
    				//System.out.println("aaaaaaaaaaaaaaaaaxxx = "  + argValues.get(2));
    			}
    			else if(result.getAttributeValue() instanceof BagAttribute)
    			{
				//Neu tham so dau vao la AttributeSelector thi tra ve cac gia tri
				//trong bag vao mang args[]

    				BagAttribute bag = (BagAttribute) result.getAttributeValue();
    				Iterator iterator;
    				iterator = bag.iterator();


    				System.out.println("bagSize " + bag.size());
    				while(iterator.hasNext()){ 
    					argValues.add((DateAttribute) iterator.next());

    				}

    			}


}

    		// if no error occurred then we got here, so we return no errors
    		return null;
}

    
    
    public void checkInputs(List inputs) throws IllegalArgumentException {
        // check that none of the inputs is a bag
        Object [] list = inputs.toArray();
        //System.out.println("input list data type" + list[0]);
        for (int i = 0; i < list.length; i++)
        {
        	if(list[i] instanceof AttributeSelector)
        	{
        		//System.out.println("input list " + i + list[i]);
        		if (!((AttributeSelector)(list[i])).evaluatesToBag())
        			throw new IllegalArgumentException("can't use bags");
        	}
        }
        // if we got here then there were no bags, so ask the other check
        // method to finish the checking
       // checkInputsNoBag(inputs);
    }
 
}
